Semantik Web • Hafta 08
Java ile OWL API — I
Neden API gerekli, hangi OWL elemanları programlanabilir, alerji ontolojisinin sıfırdan kodla kurulması
Lisansüstü Semantik Web Dersi • CMPE 583
Hafta 08 • Kazanımlar
Bu hafta sonunda
- OWL API'nin mimarisini (manager, data factory, ontology) açıklayabileceksiniz.
- Her OWL elemanının API karşılığını bulabileceksiniz.
- Alerji ontolojisini sıfırdan kodla kurabileceksiniz.
- Aksiyom ekleme, silme, arama ve kaydetme işlemlerini yapabileceksiniz.
- Değişiklik yönetimi ve hata ayıklama tekniklerini uygulayabileceksiniz.
01
Ödev 7'nin Çözümü
BMI + risk kuralı ve kural sırası.
Çözüm 7.1 — ObeseAtRisk kuralı
Person(?p) ^ hasBMI(?p, ?b) ^ swrlb:greaterThan(?b, 30.0)
^ Effected_Allergen(?p, ?f)
-> ObeseAtRisk(?p)
- S4'ten önce çalışamaz — hasBMI henüz yoktur; motor sırayı kendi bulur.
- Tetiklenen: TC_004 (BMI 33.43, Soy_Lecitin → Egg).
- OWL ile yazılabilir mi? Kısmen: veri aralığı + kısıt ile evet, ama hasBMI'yi üretmek için kural şart.
ObeseAtRisk = [TC_004]
02
Neden OWL API?
Protégé yeter mi? Nerede yetmez?
Protégé nerede yetmez?
| Senaryo | Protégé | OWL API |
| 10.000 ürünü içe almak | Elle imkânsız | Döngüyle dakikalar |
| Gece güncellenen katalog | İnsan gerekir | Zamanlanmış iş |
| Web servisinden risk sorgusu | Mümkün değil | Servis arka ucu |
| Birim testi ile doğrulama | Yok | JUnit |
| Sürüm kontrolüne uygun üretim | Elle kaydetme | Kod = tek doğru kaynak |
| Kural sonucunu raporlama | Ekrandan okuma | JSON / PDF üretimi |
Protégé tasarım aracıdır; OWL API üretim aracıdır. İkisi birbirini dışlamaz.
Neden düz RDF kütüphanesi değil?
Jena / RDF4J
Üçlü düzeyinde çalışır. Bir kısıt yazmak için blank node zincirini elle kurmanız gerekir.
6–8 triple elle
+ blank node yönetimi
OWL API
Aksiyom düzeyinde çalışır. Kısıt tek nesnedir; serileştirme API'nin işidir.
df.getOWLObjectSomeValuesFrom(
contain, additives)
Ayrıca OWL API, reasoner arayüzünü (OWLReasoner) standartlaştırır: HermiT, Pellet, JFact aynı kodla değiştirilir.
OWL API mimarisi
OWLOntologyManagerYükleme, kaydetme, değişiklik uygulama
OWLDataFactoryVarlık ve aksiyom üretimi
OWLOntologyAksiyom kümesi (sıra yok)
OWLReasonerÇıkarım, tutarlılık
OWLOntologyManager man = OWLManager.createOWLOntologyManager();
OWLDataFactory df = man.getOWLDataFactory();
OWLOntology ont = man.createOntology(
IRI.create("http://EMU/AllergyOntology"));
Ontoloji bir aksiyom kümesidir
- Sıra yoktur: aynı aksiyomları farklı sırada eklemek aynı ontolojiyi verir.
- Tekrar yoktur: aynı aksiyomu iki kez eklemek sayıyı artırmaz.
- Varlıklar (sınıf, özellik, birey) kendi başına ontolojiye ait değildir; onları aksiyomlar taşır.
- Bu yüzden yeni bir sınıf "yaratmak" için DeclarationAxiom eklenir.
En sık yapılan hata: df.getOWLClass(...) çağırıp sınıfın ontolojiye eklendiğini sanmak. O çağrı yalnızca bir referans üretir.
Hangi OWL elemanı programlanabilir?
| OWL elemanı | API karşılığı |
| Class | OWLClass + OWLDeclarationAxiom |
| SubClassOf | OWLSubClassOfAxiom |
| EquivalentClasses | OWLEquivalentClassesAxiom |
| DisjointClasses | OWLDisjointClassesAxiom |
| ObjectProperty | OWLObjectProperty + domain/range aksiyomları |
| DataProperty | OWLDataProperty |
| NamedIndividual | OWLNamedIndividual + ClassAssertionAxiom |
Element haritası — devam
| OWL elemanı | API karşılığı |
| someValuesFrom | getOWLObjectSomeValuesFrom |
| allValuesFrom | getOWLObjectAllValuesFrom |
| hasValue | getOWLObjectHasValue |
| min / max / exactly | getOWLObjectMinCardinality … |
| intersectionOf / unionOf / not | getOWLObjectIntersectionOf / UnionOf / ComplementOf |
| subPropertyOf | OWLSubObjectPropertyOfAxiom |
| sameAs / differentFrom | OWLSameIndividualAxiom / DifferentIndividualsAxiom |
| HasKey | OWLHasKeyAxiom |
| SWRL kuralı | SWRLRule |
| Annotation (label, comment) | OWLAnnotationAssertionAxiom |
API tip hiyerarşisi: her şey bir OWLObject
OWLObject
├── OWLEntity (adı olan varlık)
│ ├── OWLClass
│ ├── OWLObjectProperty
│ ├── OWLDataProperty
│ ├── OWLNamedIndividual
│ ├── OWLDatatype
│ └── OWLAnnotationProperty
├── OWLClassExpression (sınıf ifadesi)
│ ├── OWLClass
│ ├── OWLObjectSomeValuesFrom
│ ├── OWLObjectIntersectionOf …
└── OWLAxiom (ifade / aksiyom)
├── OWLSubClassOfAxiom
├── OWLClassAssertionAxiom …
- OWLEntity: IRI'si olan varlık. Tek başına anlam taşımaz.
- OWLClassExpression: sınıf ya da anonim sınıf ifadesi. OWLClass ikisinin de altındadır.
- OWLAxiom: ontolojiye eklenebilen tek şey.
- Bütün nesneler değişmezdir (immutable): bir aksiyomu düzenlemek yerine silip yenisini eklersiniz.
Bu hiyerarşiyi bilmek, hangi metodun ne döndürdüğünü tahmin etmenizi sağlar — JavaDoc'a bakmadan.
Varlık üretmek ≠ ontolojiye eklemek
Yalnızca referans
OWLClass c = df.getOWLClass(
IRI.create(NS + "Vegan"));
// ontolojide HICBIR SEY yok
ont.getAxiomCount(); // degismedi
Gerçek ekleme
man.addAxiom(ont,
df.getOWLDeclarationAxiom(c));
// artik ontolojide gorunur
ont.getAxiomCount(); // +1
Data factory bir fabrikadır, depo değildir. Aynı IRI için çağırdığınız her getOWLClass aynı nesneyi verir; ontolojiyi değiştiren tek şey addAxiom'dur.
OWL 2 profilleri ve API ile denetimi
| Profil | Amacı | Alerji projesine uygun mu |
| OWL 2 EL | Çok büyük taksonomiler (tıp) | Hayır — only ve sayı kısıtı yok |
| OWL 2 QL | Veritabanı üstü sorgu | Hayır — çıkarım sınırlı |
| OWL 2 RL | Kural motoru ile ölçekleme | Kısmen |
| OWL 2 DL | Tam ifade gücü, karar verilebilir | Evet — projenin profili |
OWL2DLProfile profile = new OWL2DLProfile();
OWLProfileReport report = profile.checkOntology(ont);
System.out.println("DL uyumlu mu? " + report.isInProfile());
report.getViolations().forEach(System.out::println);
Kural eklemek ontolojiyi DL dışına çıkarmaz; SWRL ayrı bir katmandır ve DL-safe kısıtla güvence altına alınır.
İçe alma (import) ve closure
// Servis ontolojisi alerji ontolojisini
// ice alir
man.applyChange(new AddImport(serviceOnt,
df.getOWLImportsDeclaration(
IRI.create("http://EMU/AllergyOntology"))));
// Yerel dosya eslemesi (internet gerekmez)
man.getIRIMappers().add(
new AutoIRIMapper(new File("."), true));
// Ice alinanlarla birlikte oku
ont.getAxioms(Imports.INCLUDED);
- Imports.EXCLUDED: yalnızca bu ontolojinin aksiyomları (varsayılan).
- Imports.INCLUDED: içe alınan bütün ontolojiler dahil.
- Reasoner daima closure üzerinde çalışır — içe alınanları görür.
- AutoIRIMapper, uzak IRI'leri yerel dosyalara eşler; çevrimdışı çalışmayı sağlar.
Değişiklik dinleyicisi: denetim izi
man.addOntologyChangeListener(changes -> {
for (OWLOntologyChange ch : changes) {
System.out.println((ch.isAddAxiom() ? "EKLENDI: " : "SILINDI: ")
+ ch.getAxiom());
}
});
// Bu andan sonra her degisiklik loglanir
man.addAxiom(ont, df.getOWLDeclarationAxiom(cls("Vegan")));
Gıda güvenliği gibi alanlarda "bu aksiyomu kim, ne zaman ekledi" sorusu denetim gerekliliğidir. Listener, Hafta 01'deki Trust katmanının pratik karşılığıdır.
Serileştirme formatları ve seçim
| Format sınıfı | Çıktı | Ne zaman |
| RDFXMLDocumentFormat | RDF/XML | Protégé uyumu, projenin varsayılanı |
| TurtleDocumentFormat | Turtle | İnsan okuması, kod incelemesi |
| FunctionalSyntaxDocumentFormat | Functional | Aksiyom yapısını görmek |
| ManchesterSyntaxDocumentFormat | Manchester | Kısıtları okumak |
| OWLXMLDocumentFormat | OWL/XML | XML araç zinciri |
// Ayni ontoloji, iki formatta
man.saveOntology(ont, new TurtleDocumentFormat(),
IRI.create(new File("allergy.ttl").toURI()));
man.saveOntology(ont, new FunctionalSyntaxDocumentFormat(),
IRI.create(new File("allergy.ofn").toURI()));
Aksiyom kümesi aynıdır; yalnızca yazım değişir. Sürüm kontrolünde Turtle veya Functional, diff okunabilirliği için tercih edilir.
03
Ortam Kurulumu
Maven, NetBeans ve sürüm uyumu.
pom.xml — 1: derleyici ve OWL API
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependency>
<groupId>net.sourceforge.owlapi</groupId>
<artifactId>owlapi-distribution</artifactId>
<version>4.5.29</version>
</dependency>
- 1.8: SWRLAPI Java 8 ile en güvenli çalışır.
- owlapi-distribution hepsi bir arada paket: API + ayrıştırıcılar + yazıcılar.
- Daha ince paketleme isterseniz owlapi-api + owlapi-rio ayrı alınır.
- 4.x dalı Protégé 5.6 ve SWRLAPI 2.x ile uyumludur.
pom.xml — 2: reasoner ve kural motoru
<dependency> <!-- HermiT -->
<groupId>net.sourceforge.owlapi</groupId>
<artifactId>org.semanticweb.hermit</artifactId>
<version>1.4.5.519</version>
</dependency>
<dependency> <!-- SWRL + Drools -->
<groupId>edu.stanford.swrl</groupId>
<artifactId>swrlapi-drools-engine</artifactId>
<version>2.1.2</version>
</dependency>
- HermiT sürüm numarasının sonundaki .519 hangi OWL API dalına derlendiğini söyler.
- SWRLAPI, Drools'u kendi getirir — ayrıca eklemeyin.
- Çakışma denetimi: mvn dependency:tree.
- Kural: bütün proje tek OWL API dalına sabitlenir.
NoSuchMethodError alıyorsanız neredeyse her zaman neden budur.
NetBeans proje yapısı
AllergyReasoner/
├── pom.xml
├── ALLERGY_FIXED.owl
└── src/main/java/edu/emu/allergy/
├── Main.java
├── OntologyBuilder.java
├── OntologyGateway.java
└── RiskReport.java
- OWL dosyası proje kökünde: new File("ALLERGY_FIXED.owl") çalışır.
- Kaynak içine koyarsanız getResourceAsStream kullanın.
- Paket adı IRI ile aynı olmak zorunda değildir.
04
Ontolojiyi Sıfırdan Kurmak
Alerji ontolojisi, satır satır kodla.
Adım 1a — Builder sınıfının alanları
public class OntologyBuilder {
static final String NS =
"http://EMU/AllergyOntology#";
private final OWLOntologyManager man =
OWLManager.createOWLOntologyManager();
private final OWLDataFactory df =
man.getOWLDataFactory();
private final OWLOntology ont;
}
- Üç alan: manager, data factory, ontology.
- NS sonundaki # kritiktir — eksikse bütün IRI'ler yanlış olur ve hata alınmaz.
- Data factory manager'dan alınır; ayrıca üretilmez.
Adım 1b — Yardımcı metotlar
public OntologyBuilder() throws Exception {
ont = man.createOntology(
IRI.create("http://EMU/AllergyOntology"));
}
private OWLClass cls(String n) {
return df.getOWLClass(IRI.create(NS + n));
}
private OWLObjectProperty op(String n) { … }
private OWLDataProperty dp(String n) { … }
private OWLNamedIndividual ind(String n) { … }
private void add(OWLAxiom ax) {
man.addAxiom(ont, ax);
}
- Ontoloji IRI'sinde # yoktur; namespace'te vardır.
- Dört kısayol, kodun geri kalanını okunur tutar.
- add() tek giriş noktasıdır — log veya doğrulama eklemek kolaylaşır.
Bu altı satırlık altyapı, sonraki 100 satırı yarıya indirir.
Adım 2a — Sınıfları bildir
String[] tops = {"Person", "Product",
"FoodAdditives", "Allergy"};
for (String c : tops)
add(df.getOWLDeclarationAxiom(cls(c)));
- cls(c) yardımcısı IRI'yi kurar: NS + "Person".
- DeclarationAxiom sınıfın var olduğunu bildirir.
- Bu olmadan sınıf yalnızca başka bir aksiyomda geçtiğinde görünür.
- Protégé karşılığı: sınıf ağacına yeni düğüm eklemek.
4 aksiyom eklendi.
Adım 2b — Hiyerarşiyi kur
// Adult ⊑ Person
add(df.getOWLSubClassOfAxiom(
cls("Adult"), cls("Person")));
// PersonAtRisk ⊑ Person
add(df.getOWLSubClassOfAxiom(
cls("PersonAtRisk"), cls("Person")));
- İlk argüman alt sınıf, ikincisi üst sınıf.
- Sıra ters yazılırsa hata alınmaz — anlam ters döner. En sinsi hatadır.
- Bu iki sınıf elle doldurulmaz: üyeliği S5 ve S7 kuralları yazar.
- Declaration ayrıca gerekmez; SubClassOf varlığı zaten ima eder.
2 aksiyom eklendi.
Adım 2c — Ayrıklığı bildir
Set<OWLClass> disjoint = new HashSet<>();
for (String c : tops)
disjoint.add(cls(c));
add(df.getOWLDisjointClassesAxiom(disjoint));
- Dört üst sınıf ikili ikili ayrık olur: bir birey aynı anda hem kişi hem ürün olamaz.
- Bu aksiyom olmadan yanlış tip bildirimleri sessizce kabul edilir.
- Hafta 05'teki tutarsızlık örneği (TC_009 Contain Nisin) ancak bu sayede yakalanır.
- Protégé karşılığı: "Disjoint With" satırı.
1 aksiyom. Toplam: 4 + 2 + 1 = 7 aksiyom.
Adım 3a — Yardımcı metot: üç aksiyom bir arada
private void otp(String name,
String domain,
String range) {
add(df.getOWLDeclarationAxiom(op(name)));
add(df.getOWLObjectPropertyDomainAxiom(
op(name), cls(domain)));
add(df.getOWLObjectPropertyRangeAxiom(
op(name), cls(range)));
}
- Her nesne özelliği üç aksiyom ister: bildirim, domain, range.
- Yardımcı metot yazmak, 9 özellik × 3 aksiyom = 27 satırı 9 satıra indirir.
- Hatırlatma: domain/range bir kısıt değil, çıkarım kaynağıdır (Hafta 03).
Adım 3b — Beş temel ilişki
otp("hasAllergy", "Person", "Allergy");
otp("ChooseProduct", "Person", "Product");
otp("Contain", "Product", "FoodAdditives");
otp("Triggers", "FoodAdditives", "Allergy");
otp("Effected_Allergen",
"Person", "FoodAdditives");
- İlk dördü girdi verisidir; elle bildirilir.
- Effected_Allergen ise çıktıdır: değerini S6 kuralı yazar.
- Risk zinciri bu beş ilişkiyle kapanır: Person → Product → FoodAdditives → Allergy → Person.
15 aksiyom eklendi.
Adım 3c — Alerjene özgü alt özellikler
for (String a : new String[]{
"Lactose","Egg","Fish","Gluten"}) {
String sub = a + "_Allergen";
otp(sub, "Person", "FoodAdditives");
add(df.getOWLSubObjectPropertyOfAxiom(
op(sub), op("Effected_Allergen")));
}
- Dört özellik üretilir: Lactose_Allergen … Gluten_Allergen.
- Hepsi Effected_Allergen altındadır.
- Kazanç: S1–S3 alt özelliği yazar, RDFS üst özelliğe yükseltir, S7 yalnızca üst özelliğe bakar.
4 × (3+1) = 16 aksiyom. Bölüm toplamı: 31 aksiyom.
Adım 4 — Veri özellikleri
private void dtp(String name,
OWLDatatype type,
String domain) {
add(df.getOWLDeclarationAxiom(dp(name)));
add(df.getOWLDataPropertyDomainAxiom(
dp(name), cls(domain)));
add(df.getOWLDataPropertyRangeAxiom(
dp(name), type));
}
| Özellik | Tip | Kaynak |
| hasName | String | elle |
| hasAge | Integer | elle |
| hasWeight | Double | elle |
| hasHeight | Double | elle |
| hasBMI | Double | S4 kuralı |
| hasProductName | String | elle |
dtp("hasAge", df.getIntegerOWLDatatype(), "Person");
dtp("hasWeight", df.getDoubleOWLDatatype(), "Person");
Adım 5a — Alerji bireyleri
for (String a : new String[]{
"Lactose","Egg","Fish","Gluten"})
add(df.getOWLClassAssertionAxiom(
cls("Allergy"), ind(a)));
- ClassAssertionAxiom = "bu birey şu sınıfın üyesidir".
- Protégé karşılığı: bireyin "Types" satırı.
- Alerjileri birey yaptık, sınıf yapmadık: yeni alerji eklemek model değişikliği gerektirmesin.
4 aksiyom.
Adım 5b — Katkı maddeleri ve tetikleme
Map<String,String> t = new LinkedHashMap<>();
t.put("Nisin", "Lactose");
t.put("Casein", "Lactose");
t.put("Soy_Lecitin", "Egg");
t.put("Sodium_Ascorbite", "Fish");
t.put("Alginic_Acid", "Gluten");
t.put("Ascorbic_Acid", null);
t.put("Phospore", null);
- null = tetikleme bilgisi bilinmiyor.
- Açık dünya gereği bu "tetiklemez" demek değildir.
- Bu iki katkı, projenin OWA örneğidir.
Adım 5c — Aksiyomları üret
t.forEach((additive, allergy) -> {
add(df.getOWLClassAssertionAxiom(
cls("FoodAdditives"), ind(additive)));
if (allergy != null)
add(df.getOWLObjectPropertyAssertionAxiom(
op("Triggers"),
ind(additive), ind(allergy)));
});
- ObjectPropertyAssertionAxiom(P, özne, nesne) — argüman sırası budur.
- 7 tip bildirimi + 5 tetikleme = 12 aksiyom.
- Protégé karşılığı: "Object property assertions" satırları.
Bölüm toplamı: 4 + 12 = 16 aksiyom.
Adım 6 — Ürün bireyleri
void product(String ean, String name, String... additives) {
add(df.getOWLClassAssertionAxiom(cls("Product"), ind(ean)));
add(df.getOWLDataPropertyAssertionAxiom(
dp("hasProductName"), ind(ean), df.getOWLLiteral(name)));
for (String a : additives)
add(df.getOWLObjectPropertyAssertionAxiom(
op("Contain"), ind(ean), ind(a)));
}
product("EAN_00001","ETI Cracker",
"Alginic_Acid");
product("EAN_00004","Eti Chocolate",
"Ascorbic_Acid","Nisin","Soy_Lecitin");
- String... değişken sayıda katkı alır.
- Barkod kimliktir, ürün adı veridir — ayrı tutulur.
- Ad için tip vermedik: getOWLLiteral(String) otomatik xsd:string üretir.
Adım 7 — Kişi bireyleri
void person(String tc, String name, int age, double w, double h,
String choice, String... allergies) {
add(df.getOWLClassAssertionAxiom(cls("Person"), ind(tc)));
dval("hasName", tc, df.getOWLLiteral(name));
dval("hasAge", tc, df.getOWLLiteral(age)); // xsd:int
dval("hasWeight",tc, df.getOWLLiteral(w)); // xsd:double
dval("hasHeight",tc, df.getOWLLiteral(h));
oval("ChooseProduct", tc, choice);
for (String a : allergies) oval("hasAllergy", tc, a);
}
person("TC_001","Ayse",38,67.5,1.68,
"EAN_00004","Lactose");
person("TC_003","MEHMET",35,93.0,1.87,
"EAN_00003","Fish","Lactose");
- int ve double parametreleri doğru literal tipini garanti eder.
- BMI burada yoktur — S4 kuralı yazacak.
- Bir kişi birden çok alerji taşıyabilir: String...
Literal üretimi: tip önemlidir
| Çağrı | Üretilen literal | S4/S5 çalışır mı |
| getOWLLiteral(38) | "38"^^xsd:int | Evet |
| getOWLLiteral(67.5) | "67.5"^^xsd:double | Evet |
| getOWLLiteral("38") | "38"^^xsd:string | Hayır |
| getOWLLiteral("Ayse") | "Ayse"^^xsd:string | — |
| getOWLLiteral("Riskli", "tr") | "Riskli"@tr | Etiket |
Java'nın aşırı yükleme (overload) seçimi burada davranışı belirler: int mi String mi verdiğinize dikkat edin.
Adım 8a — "En az bir katkı içerir"
// Product ⊑ ∃Contain.FoodAdditives
OWLClassExpression expr =
df.getOWLObjectSomeValuesFrom(
op("Contain"),
cls("FoodAdditives"));
add(df.getOWLSubClassOfAxiom(
cls("Product"), expr));
- Kısıt bir anonim sınıftır: "en az bir katkı içeren şeyler".
- Protégé'de bunu Contain some FoodAdditives diye yazarsınız.
- API iki adımda kurar: önce ifade, sonra aksiyom.
- RDF/XML'de blank node zinciri olur — API sizi bundan korur.
Adım 8b — İç içe kısıt: RiskyProduct
// RiskyProduct ≡ Product ⊓ ∃Contain.(∃Triggers.Allergy)
OWLClassExpression inner = // ic kisit
df.getOWLObjectSomeValuesFrom(op("Triggers"), cls("Allergy"));
OWLClassExpression outer = // dis kisit
df.getOWLObjectSomeValuesFrom(op("Contain"), inner);
add(df.getOWLEquivalentClassesAxiom(cls("RiskyProduct"),
df.getOWLObjectIntersectionOf(cls("Product"), outer)));
- İfadeler içeriden dışarıya kurulur — matematikteki parantez sırası gibi.
- EquivalentClasses seçtik: koşulu sağlayan her ürün sınıfa otomatik girer.
- SubClassOf seçseydik hiçbir ürün sınıflandırılmazdı.
Adım 8c — Belirli bir bireye bağlanmak
// LactoseIntolerantPerson ≡
// Person ⊓ hasAllergy value Lactose
add(df.getOWLEquivalentClassesAxiom(
cls("LactoseIntolerantPerson"),
df.getOWLObjectIntersectionOf(
cls("Person"),
df.getOWLObjectHasValue(
op("hasAllergy"),
ind("Lactose")))));
- getOWLObjectHasValue bir bireye bağlanır.
- getOWLObjectSomeValuesFrom ise bir sınıfa.
- Karıştırmak boş sınıfların en yaygın nedenidir.
- Üyeler (reasoner sonrası): TC_001, TC_002, TC_003.
Adım 9 — İki dilli etiketler
void label(OWLEntity e, String tr, String en) {
add(df.getOWLAnnotationAssertionAxiom(
df.getRDFSLabel(), e.getIRI(), df.getOWLLiteral(tr, "tr")));
add(df.getOWLAnnotationAssertionAxiom(
df.getRDFSLabel(), e.getIRI(), df.getOWLLiteral(en, "en")));
}
void buildLabels() {
label(cls("PersonAtRisk"), "Riskli Kisi", "Person At Risk");
label(cls("FoodAdditives"), "Katki Maddesi", "Food Additive");
label(op("Triggers"), "tetikler", "triggers");
label(ind("Soy_Lecitin"), "Soya lesitini", "Soy Lecithin");
}
Etiketler çıkarımı etkilemez; yalnızca Protégé ve arayüz gösterimi içindir.
Adım 10 — Kaydet ve doğrula
public OWLOntology build() throws Exception {
buildClasses(); buildObjectProperties(); buildDataProperties();
buildAllergiesAndAdditives(); buildProducts(); buildPersons();
buildRestrictions(); buildLabels();
System.out.println("Aksiyom: " + ont.getAxiomCount());
System.out.println("Mantiksal aksiyom: " + ont.getLogicalAxiomCount());
man.saveOntology(ont, new RDFXMLDocumentFormat(),
IRI.create(new File("ALLERGY_GENERATED.owl").toURI()));
return ont;
}
Aksiyom: 121 Mantiksal aksiyom: 96
05
Okuma, Arama, Değiştirme
EntitySearcher, aksiyom filtreleri ve değişiklik yönetimi.
Envanter okuma
System.out.println("Sinif : "
+ ont.getClassesInSignature().size());
System.out.println("Nesne oz.: "
+ ont.getObjectPropertiesInSignature().size());
System.out.println("Veri oz. : "
+ ont.getDataPropertiesInSignature().size());
System.out.println("Birey : "
+ ont.getIndividualsInSignature().size());
- Signature = ontolojide adı geçen bütün varlıklar.
- getAxiomCount() ise aksiyom sayısıdır — ikisi farklı ölçüdür.
- Bu dört satır, kodla üretilen dosyayı Protégé metrikleriyle karşılaştırmanın en hızlı yolu.
Sinif: 8 · Nesne oz.: 9 · Veri oz.: 6 · Birey: 17
EntitySearcher ile değer okuma
// Bir kisinin alerjileri
EntitySearcher.getObjectPropertyValues(ind("TC_003"), op("hasAllergy"), ont)
.forEach(v -> System.out.println(v));
// Bir kisinin adi (data property)
EntitySearcher.getDataPropertyValues(ind("TC_003"), dp("hasName"), ont)
.forEach(l -> System.out.println(l.getLiteral()));
// Bir sinifin bildirilmis bireyleri
EntitySearcher.getIndividuals(cls("Product"), ont)
.forEach(i -> System.out.println(i.getIRI().getShortForm()));
Dikkat: EntitySearcher yalnızca bildirilmiş aksiyomları okur. Çıkarılan bilgi için reasoner gerekir (Hafta 09).
Aksiyom türüne göre arama
// Butun Contain bildirimleri
ont.getAxioms(AxiomType.OBJECT_PROPERTY_ASSERTION).stream()
.filter(ax -> ax.getProperty().equals(op("Contain")))
.forEach(ax -> System.out.println(
ax.getSubject() + " icerir " + ax.getObject()));
// Bir sinifla ilgili tum aksiyomlar
ont.getAxioms(cls("Person"), Imports.INCLUDED)
.forEach(System.out::println);
// SWRL kurallari
System.out.println("Kural sayisi: " + ont.getAxioms(AxiomType.SWRL_RULE).size());
EAN_00004 icerir Nisin · EAN_00003 icerir Casein · …
Değişiklik yönetimi
// Toplu degisiklik listesi
List<OWLOntologyChange> changes = new ArrayList<>();
changes.add(new AddAxiom(ont, df.getOWLClassAssertionAxiom(
cls("Person"), ind("TC_005"))));
changes.add(new RemoveAxiom(ont, df.getOWLObjectPropertyAssertionAxiom(
op("Contain"), ind("EAN_00001"), ind("Alginic_Acid"))));
List<OWLOntologyChange> applied = man.applyChanges(changes);
System.out.println("Uygulanan degisiklik: " + applied.size());
Silme işleminde aksiyomun birebir aynı olması gerekir; literal tipi farklıysa silme sessizce başarısız olur ve applied boş döner.
Ontolojiyi nereden yükleyebilirsiniz?
// 1) Dosyadan
man.loadOntologyFromOntologyDocument(new File("ALLERGY_FIXED.owl"));
// 2) URL'den
man.loadOntology(IRI.create("http://EMU/AllergyOntology"));
// 3) Classpath icinden (jar ile paketlenmis)
man.loadOntologyFromOntologyDocument(
OntologyGateway.class.getResourceAsStream("/ALLERGY_FIXED.owl"));
// 4) Metinden
man.loadOntologyFromOntologyDocument(
new StringDocumentSource(turtleText));
Import zinciri için AutoIRIMapper kullanın; aksi hâlde uzak import'lar internet erişimi gerektirir.
Sık hatalar ve tanısı
| Belirti | Neden | Çözüm |
| Boş sonuç, hata yok | NS sonundaki # eksik | NS sabitini denetle |
| Aksiyom sayısı artmıyor | Başka ontoloji nesnesine eklendi | Tek ont kullan |
| Kural boş dönüyor | Literal tipi string | getOWLLiteral(38) |
| Silme çalışmıyor | Aksiyom birebir değil | Önce arayıp bulunanı sil |
| NoSuchMethodError | OWL API 4/5 karışık | Tek dala sabitle |
| Import bulunamadı | Uzak IRI erişilemez | AutoIRIMapper |
Ürettiğiniz dosyayı Protégé'de doğrulayın
ALLERGY_GENERATED.owl › Ontology metrics
Metrics
Axiom 121
Logical axiom 96
Class count 8
Object property 9
Data property 6
Individual 17
Class hierarchy
▾ owl:Thing
▾ Person
Adult · PersonAtRisk
▾ Product
RiskyProduct (inferred)
FoodAdditives · Allergy
Şematik gösterim. Kodla üretilen dosya Protégé'de açılıp elle incelenebilir olmalıdır — bu, en hızlı doğrulama yöntemidir.
06
Ödev ve Proje Adımı
Ontolojinizi kodla üretin.
Ödev 8 — Programatik ontoloji
- Kendi ontolojinizi sıfırdan Java ile kurun (sınıf, özellik, birey, kısıt, etiket).
- Verileri koda gömmek yerine CSV'den okuyun; en az 20 ürün üretin.
- Envanter raporu yazdırın ve Protégé metrikleriyle karşılaştırın.
- Bir aksiyomu bulup silen ve doğrulayan bir metot yazın.
- Üretilen dosyayı Protégé'de açıp hiyerarşinin doğruluğunu gösterin.
Teslim
Maven projesi + CSV + üretilen .owl + konsol çıktısı + Protégé ekran görüntüleri.
Çözümü Hafta 09'un başında ele alacağız.
Değerlendirme ölçütleri
| Ölçüt | Ağırlık | Beklenen |
| Kod yapısı | 20% | Yardımcı metotlar, tekrar yok |
| Eleman kapsamı | 25% | Sınıf, OTP, DTP, birey, kısıt, etiket |
| Literal tipleri | 15% | int/double doğru |
| Veri kaynağından üretim | 20% | CSV → ontoloji çalışıyor |
| Doğrulama | 20% | Metrikler karşılaştırılmış |
Kaynaklar ve referanslar
- Horridge, M., Bechhofer, S. — The OWL API: A Java API for OWL Ontologies, Semantic Web Journal, 2011.
- OWL API kaynak kodu ve örnekleri — github.com/owlcs/owlapi; wiki'deki "Examples" sayfası.
- OWL API JavaDoc — OWLDataFactory ve OWLOntologyManager arayüzleri.
- W3C — OWL 2 Structural Specification and Functional-Style Syntax (API'nin aksiyom modelinin kaynağı).
- W3C — OWL 2 Primer; kısıt ve aksiyom türleri.
- Horridge, M. — A Practical Guide To Building OWL Ontologies Using Protégé 5.
- Glimm, B. et al. — HermiT: An OWL 2 Reasoner, Journal of Automated Reasoning, 2014.
Özet • 1 / 2
API mimarisi
- Manager dosya işlerini, data factory üretimi, ontology aksiyomları taşır.
- Ontoloji sırasız, tekrarsız bir aksiyom kümesidir.
- getOWLClass yalnızca referans üretir; ekleme addAxiom ile olur.
- API aksiyom düzeyinde çalışır; blank node yönetimi sizden gizlenir.
Özet • 2 / 2
Proje ve sonraki adım
- Alerji ontolojisinin tamamı ~120 aksiyomla kodla üretilebiliyor.
- Literal tipi, kuralların çalışmasının ön koşulu.
- EntitySearcher yalnızca bildirilmiş bilgiyi okur.
- Silme için aksiyom birebir eşleşmelidir.
Hafta 09'da
OWL API-II ve reasoner: HermiT/Pellet ile tutarlılık, sınıflandırma, gerçekleme ve çıkarımın kalıcı yazılması.
Ayrıca: Ödev 8'in ayrıntılı çözümü.
Tekrar Soruları
Kendinizi sınayın
- Neden düz RDF kütüphanesi yerine OWL API?
- getOWLClass ontolojiye ne ekler?
- Aksiyom kümesinin sırasız olması ne sağlar?
- DeclarationAxiom hangi durumda zorunludur?
- Literal tipi hatası kendini nasıl gösterir?
- EntitySearcher ile reasoner farkı nedir?
- Silme neden sessizce başarısız olur?
- AutoIRIMapper hangi sorunu çözer?
Alıştırma • Sınıf içi
Kodu tamamlayın
EAN_00005 (Protein Biscuit, Whey_Protein + Wheat_Starch) ontolojiye kodla eklenecek.
add(df.get________Axiom(
cls("Product"), ind("EAN_00005")));
add(df.get________Axiom(
op("Contain"), ind("EAN_00005"),
ind("Whey_Protein")));
add(df.get________Axiom(
op("Triggers"), ind("Whey_Protein"),
ind("Lactose")));
Sorular
- Kaç aksiyom eklendi?
- Hangi kişi için S6 tetiklenir?
- Declaration aksiyomu gerekli mi?
Çözüm Hafta 09'da.